#include "disk.hpp"

#include <physfs.h>

#include <iostream>

bool Disk::Open(const char *arg0)
{
	bool success = PHYSFS_init(arg0);

	if (success)
	{
		success = PHYSFS_mount(PHYSFS_getBaseDir(), NULL, true);
	}

	if (success)
	{
		std::cout << "Search Paths:" << std::endl;
		char **paths = PHYSFS_getSearchPath();

		for (int i = 0; paths[i] != NULL; ++i)
		{
			std::cout << paths[i] << std::endl;
		}

		PHYSFS_freeList(paths);
	}
	else
	{
		Error("Disk::Open", arg0);
	}

	return success;
}

bool Disk::AutoSetup()
{
	const char *ORG = "aria";
	const char *APP = "aria";
	const char *PAK = "pk7";
	
	if (!PHYSFS_setSaneConfig(ORG, APP, PAK, false, false))
	{
		Error("Disk::AutoSetup", "");
		return false;
	}
	return true;
}

void Disk::Close()
{
	PHYSFS_deinit();
}

bool Disk::FExists(const char *name)
{
	return PHYSFS_exists(name);
}

#include <cstdlib>
#include <cstring>

int Disk::CStrOpen(const char *name, char **textp)
{
	PHYSFS_File *file = PHYSFS_openRead(name);
	bool success = (file != NULL);
	int readct = 0;
	char *text = NULL;

	if (!success)
	{
		Error("Disk::TextOpen", name);
		return 0;
	}

	const int BUFSIZE = 256;
	char buf[BUFSIZE];
	int bufreadct = 0;

	do
	{
		bufreadct = PHYSFS_read(file, buf, 1, BUFSIZE);

		if (bufreadct > 0)
		{
			text = (char*)std::realloc(text, readct + bufreadct);
			if (text)
			{
				std::memcpy(&text[readct], buf, bufreadct);
				readct += bufreadct;
			}
		}
	}
	while (!PHYSFS_eof(file) && bufreadct > 0);

	success = PHYSFS_eof(file);
	PHYSFS_close(file);


	if (success)
	{
		*textp = text;
	}
	else
	{
		Error("Disk::TextOpen", name);
	}

	return readct;
}

void Disk::CStrClose(char *text)
{
	free(text);
}

int Disk::TextOpen(const char *name, std::string & text)
{
	PHYSFS_File *file = PHYSFS_openRead(name);
	bool success = (file != NULL);
	int readct = 0;

	if (success)
	{
		const int BUFSIZE = 256;
		char buf[BUFSIZE];
		int bufreadct = 0;

		do
		{
			bufreadct = PHYSFS_read(file, buf, 1, BUFSIZE);
			if (bufreadct > 0)
			{
				text.append(buf, bufreadct);
				readct += bufreadct;
			}
		}
		while (!PHYSFS_eof(file) && bufreadct > 0);

		success = PHYSFS_eof(file);
		PHYSFS_close(file);
	}

	if (!success)
	{
		Error("Disk::TextOpen", name);
	}

	return readct;
}

int Disk::TextSave(const char *name, const std::string & text)
{
	PHYSFS_File *file = PHYSFS_openWrite(name);
	int writect = 0;
	bool success = (file != NULL);

	if (success)
	{
		writect = PHYSFS_write(file, text.c_str(), 1, text.size());
		PHYSFS_close(file);
		success = writect > 0 && (unsigned)writect == text.size();
	}

	if (!success)
	{
		Error("Disk::TextSave", name);
	}

	return writect;
}

// void Disk::TextClose(char *text)
// {
// 	delete [] text;
// }

void Disk::SaveToBase()
{
	PHYSFS_setWriteDir(PHYSFS_getBaseDir());
}

void Disk::SaveToUser()
{
	PHYSFS_setWriteDir(PHYSFS_getUserDir());
}

void Disk::Error(const char *func, const char *name)
{
	std::cerr << func << "(" << name << "): " << PHYSFS_getLastError();
	std::cerr << std::endl;
}

Disk Dsk;
